﻿namespace YunQue.Services.System
{
    /// <summary>
    /// 权限服务接口
    /// </summary>
    public class PermissionService : YunQueBaseService, IScoped
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="serviceProvider"></param>
        public PermissionService(IServiceProvider serviceProvider) : base(serviceProvider)
        {
        }
        /// <summary>
        /// 根据用户Id获取用户权限
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<List<string>> GetUserPermissionsByUserIdAsync(string userId)
        {
            string cacheKey = AppSettingManager.CACHEKEY_USERPERMISSION + userId;
            var userPermissions = await RedisWrapper.SMembersAsync<string>(cacheKey);
            if (userPermissions == null)
            {
                userPermissions = await _dbContext.UserPermissions.Where(x => x.UserId == userId).Select(p => p.PermissionCode).ToListAsync();
                if (userPermissions == null) userPermissions = new List<string>() { AppSettingManager.CACHEKEY_EMPTY};
                await RedisWrapper.SAddListAsync(cacheKey, userPermissions);
            }
            return userPermissions.Where(p => p != AppSettingManager.CACHEKEY_EMPTY).ToList();
        }
        /// <summary>
        /// 获取租户级别的权限
        /// </summary>
        /// <param name="tenantCode"></param>
        /// <returns></returns>
        public async Task<List<string>> GetTenantPermissionsByCodeAsync(string tenantCode)
        {
            var tenantPermissions = await RedisWrapper.SMembersAsync<string>(AppSettingManager.CACHEKEY_TENANTPERMISSION + tenantCode);
            return tenantPermissions ?? new List<string>();
        }
        /// <summary>
        /// 设置用户权限
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="codes"></param>
        /// <returns></returns>
        public async Task<bool> SetUserPermissionsAsync(string userId, List<string> codes)
        {
            List<UserPermissionEntity> userPermissions = new List<UserPermissionEntity>();
            string cacheKey = AppSettingManager.CACHEKEY_USERPERMISSION + userId;
            using (var transaction = _dbContext.Database.BeginTransaction())
            {
                try
                {
                    var oldPermissions = await _dbContext.UserPermissions.Where(x => x.UserId == userId).ToListAsync();
                    List<string> removeCodes = new List<string>();
                    List<string> addCodes = new List<string>();
                    //codes 与 oldPermissions 的差集
                    if (oldPermissions.IsNotNullOrEmpty())
                    {
                        var removePermissions = oldPermissions.Where(x => !codes.Contains(x.PermissionCode)).ToList();
                        removeCodes = removePermissions.Select(x => x.PermissionCode).ToList();
                        addCodes = codes.Where(x => !oldPermissions.Select(p => p.PermissionCode).Contains(x)).ToList();
                        _dbContext.UserPermissions.RemoveRange(removePermissions);
                    }
                    else
                    {
                        addCodes = codes;
                    }
                    //添加用户权限
                    foreach (var code in addCodes)
                    {
                        userPermissions.Add(new UserPermissionEntity()
                        {
                            UserId = userId,
                            PermissionCode = code
                        });
                    }
                    await _dbContext.UserPermissions.AddRangeAsync(userPermissions).ConfigureAwait(false);
                    await _dbContext.SaveChangesAsync().ConfigureAwait(false);
                    transaction.Commit();
                    //更新缓存
                    await RedisWrapper.SAddListAsync(cacheKey, addCodes);
                    await RedisWrapper.SRemListAsync(cacheKey, removeCodes);
                    await RedisWrapper.SRemAsync(cacheKey, AppSettingManager.CACHEKEY_EMPTY);
                }
                catch (Exception ex)
                {
                    transaction.Rollback();
                    await RedisWrapper.RemoveAsync(cacheKey);
                    throw new Exception("增加权限失败",ex);
                }
            }
            return true;
        }


        /// <summary>
        /// 移除用户权限
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task<bool> RemoveUserPermissionsAsync(string userId)
        {
            string cacheKey = AppSettingManager.CACHEKEY_USERPERMISSION + userId;
            using (var transaction = _dbContext.Database.BeginTransaction())
            {
                try
                {
                    var userPermissions = await _dbContext.UserPermissions.Where(x => x.UserId == userId).ToListAsync();
                    if (userPermissions == null) throw new Exception("权限不存在");
                    _dbContext.UserPermissions.RemoveRange(userPermissions);
                    await _dbContext.SaveChangesAsync().ConfigureAwait(false);
                    transaction.Commit();
                    await RedisWrapper.SRemListAsync(cacheKey, userPermissions.Select(p=>p.PermissionCode).ToList());
                }
                catch (Exception ex)
                {
                    transaction.Rollback();
                    await RedisWrapper.RemoveAsync(cacheKey);
                    throw new Exception("删除权限失败", ex);
                }
            }
            return true;
        }
        /// <summary>
        /// 增加用户权限
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="codes"></param>
        /// <returns></returns>
        public async Task<bool> AddUserPermissionsAsync(string userId, List<string> codes)
        {
            if (codes.IsNullOrEmpty()) throw new Exception("权限不能为空");
            string cacheKey = AppSettingManager.CACHEKEY_USERPERMISSION + userId;
            var existPermissions = await GetUserPermissionsByUserIdAsync(userId).ConfigureAwait(false);
            if(existPermissions.IsNotNullOrEmpty()) codes = codes.Where(x => !existPermissions.Contains(x)).ToList();
            if(codes.IsNullOrEmpty()) return true;
            using (var transaction = _dbContext.Database.BeginTransaction())
            {
                try
                {
                    List<UserPermissionEntity> userPermissions = new List<UserPermissionEntity>();
                    foreach (var code in codes)
                    {
                        userPermissions.Add(new UserPermissionEntity()
                        {
                            UserId = userId,
                            PermissionCode = code
                        });
                    }
                    await _dbContext.UserPermissions.AddRangeAsync(userPermissions).ConfigureAwait(false);
                    await _dbContext.SaveChangesAsync().ConfigureAwait(false);
                    transaction.Commit();
                    await RedisWrapper.SAddListAsync(cacheKey, codes);
                    await RedisWrapper.SRemAsync(cacheKey, AppSettingManager.CACHEKEY_EMPTY);
                }
                catch (Exception ex)
                {
                    transaction.Rollback();
                    await RedisWrapper.RemoveAsync(cacheKey);
                    throw new Exception("增加权限失败", ex);
                }
            }
            return true;
        }
    }
}
